/*jslint vars: true, forin: true, sloppy: true */
/*global angular, ocDialog, DialogManager, DialogFactory */
var throttle = function throttle(callback, limit) {
	//from underscore
	var wait = false;
	return function () {
		if (!wait) {
			callback.apply(this, arguments);
			wait = true;
			setTimeout(function () {
				wait = false;
			}, limit);
		}
	};
}, titleMapping = [
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
	'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
	'Y', 'Z'
];

ocDialog.directive("ocGrid", function () {
	return {
		restrict: 'E',
		replace: true,
		controller: function () {},
		scope: {
			data: '=ocGridData',
			titles: '=ocGridTitles'
		},
		template:
			'<div class="oc-grid"><section class="oc-grid-bisect">Excel</section>' +

				// 横向行表头
				'<section class="oc-grid-row-header" style="left:0;">' +
				'<div ng-repeat="cell in titles" style="width: {{thSize[$index]}}px;"' +
				'ng-class="{selected:pos.col==$index}" ' +
				'>{{cell}}<hr ng-mousedown="resize($event, $index)" /></div>' +
				'</section>' +

				// 纵向列表头
				'<section class="oc-grid-col-header" style="top:0;">' +
				'<div style="height: 30px" ng-repeat="row in data track by $index"' +
				'ng-class="{selected:pos.row==$index}" ' +
				'>{{$index}}</div>' +
				'</section>' +

				// 数据滚动区
				'<div class="oc-grid-inner"><table>' +

					// 数据行表头宽度控制
					'<thead><tr><th ng-repeat="cell in data[0] track by $index">' +
					'<div style="width: {{thSize[$index]}}px"></div></th></tr></thead>' +

					// 数据渲染区
					'<tbody><tr ng-repeat="rowData in data track by $index" style="height:30px;">' +
					'<td ng-repeat="cellData in rowData track by $index" ' +
					'ng-class="{selected:pos.row==$parent.$index && pos.col==$index}" ' +
					'ng-click="selectCell($parent.$index, $index, $event)" ng-dblclick="editCell($event)">' +
					'<div>{{data[$parent.$index][$index]}}</div></td></tr></tbody>' +
				'</table><textarea ng-model="data[pos.row][pos.col]" ng-show="isEditable" class="oc-grid-input"' +
				' style="left:{{input.left}}px;top:{{input.top}}px;width:{{input.width}}px;height:{{input.height}}px">' +
				'</textarea></div></div>',
		link: function (scope, element, attr) {
			// 整理数据
			scope.thSize = []; //行头宽度表
			scope.titles = scope.titles || [];

			angular.forEach(scope.data[0], function (cell, index) {
				scope.thSize[index] = 120; //初始化行头宽度
				scope.titles[index] = titleMapping[index];
			});


			// 调整宽度
			var initLeft, initWidth, resizeHandleIndex, minWidth = 10;

			var resizing = function (event) {
				scope.$apply(function () {
					scope.thSize[resizeHandleIndex] =
						Math.max(initWidth + event.clientX - initLeft, minWidth);
				});
			};

			var cancelResizable = function () {
				element.off("mousemove", resizing);
				element.off("mouseup", cancelResizable);
			};

			scope.resize = function (event, index) {
				scope.isEditable = false;

				initLeft = event.clientX;
				initWidth = scope.thSize[index];
				resizeHandleIndex = index;

				element.on("mousemove", resizing).on("mouseup", cancelResizable);
			};

			// 选择单元格
			scope.pos = {
				row: 1,
				col: 1
			};
			scope.selectCell = function (row, col, event) {
				scope.isEditable = false;
				scope.pos = {
					row: row,
					col: col
				};
			};

			// 编辑单元格
			scope.isEditable = false;
			scope.input = {
				top: 0,
				left: 0,
				width: 0,
				height: 0
			};
			scope.editCell = function (event) {
				scope.isEditable = true;
				var $ = event.target.offsetParent;

				scope.input = {
					top: $.offsetTop,
					left: $.offsetLeft,
					width: $.offsetWidth - 1,
					height: $.offsetHeight - 1
				};

				setTimeout(function () {
					scope.inputBox[0].focus();
				}, 0);
			};
		}
	};
}).directive("ocGridInner", function () {
	return {
		restrict: "C",
		require: '^ocGrid',
		link: function (scope, element) {
			element.on('scroll', throttle(function () {
				scope.rowHeader[0].style.left = '-' + element[0].scrollLeft + 'px';
				scope.colHeader[0].style.top = '-' + element[0].scrollTop + 'px';
			}, 0));
		}
	};
}).directive("ocGridRowHeader", function () {
	return {
		restrict: "C",
		require: '^ocGrid',
		link: function (scope, element) {
			scope.rowHeader = element;
		}
	};
}).directive("ocGridInput", function () {
	return {
		restrict: "C",
		require: '^ocGrid',
		link: function (scope, element) {
			scope.inputBox = element;
		}
	};
}).directive("ocGridColHeader", function () {
	return {
		restrict: "C",
		require: '^ocGrid',
		link: function (scope, element) {
			scope.colHeader = element;
		}
	};
});

